package com.cxf.cxfdaybat.utils;

import com.cxf.cxfdaybat.entity.Person;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.spi.ValidationProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * description: ValidatorUtils <br>
 * date: 2021/11/12 19:24 <br>
 * author: cxf <br>
 * version: 1.0 <br>
 */
public class ValidatorUtils {




    private static Validator validator = Validation.byProvider(HibernateValidator.class)
                                            .configure()
                                            .failFast(false)
                                            .buildValidatorFactory()
                                            .getValidator();

    public static Validator getValidator() {
        Animal animal = new Animal() {
            @Override
            public String toString() {
                return super.toString();
            }
        };
        return validator;
    }

    /**
     * @Title: validateBean
     * @Description: 组验证
     * @Author: cxf
     * @DateTime: 2021/11/12 23:25
     * @param t
     * @param groups
     * @return com.cxf.cxfdaybat.utils.ValidatorUtils.ValidResult
     * @throws
     */
    public static <T> ValidResult validateBean(T t, Class<?>...groups) {
        ValidResult result = new ValidatorUtils().new ValidResult();
        Set<ConstraintViolation<T>> violationSet = validator.validate(t,groups);
        boolean hasError = violationSet != null && violationSet.size() > 0;
        result.setHasErrors(hasError);
        if (hasError) {
            for (ConstraintViolation<T> violation : violationSet) {
                result.addError(violation.getPropertyPath().toString(), violation.getMessage());
            }
        }
        return result;
    }

    /**
     * @Title: validateProperty
     * @Description: 字段验证
     * @Author: cxf
     * @DateTime: 2021/11/12 23:27
     * @param obj
     * @param propertyName
     * @return com.cxf.cxfdaybat.utils.ValidatorUtils.ValidResult
     * @throws
     */
    public static <T> ValidResult validateProperty(T obj, String propertyName) {
        ValidResult result = new ValidatorUtils().new ValidResult();
        Set<ConstraintViolation<T>> violationSet = validator.validateProperty(obj, propertyName);
        boolean hasError = violationSet != null && violationSet.size() > 0;
        result.setHasErrors(hasError);
        if (hasError) {
            for (ConstraintViolation<T> violation : violationSet) {
                result.addError(propertyName, violation.getMessage());
            }
        }
        return result;
    }



    public class ValidResult {

        private boolean hasErrors;
        private List<ErrorMessage> errors;

        public ValidResult() {
            this.errors = new ArrayList<>();
        }
        public boolean hasErrors() {
            return hasErrors;
        }

        public void setHasErrors(boolean hasErrors) {
            this.hasErrors = hasErrors;
        }

        public List<ErrorMessage> getAllErrors() {
            return errors;
        }

        public String getErrors(){
            StringBuilder sb = new StringBuilder();
            for (ErrorMessage error : errors) {
                sb.append(error.getPropertyPath()).append(":").append(error.getMessage()).append(" ");
            }
            return sb.toString();
        }

        public void addError(String propertyName, String message) {
            this.errors.add(new ErrorMessage(propertyName, message));
        }
    }


    public class ErrorMessage {
        private String propertyPath;
        private String message;

        public ErrorMessage() {
        }

        public ErrorMessage(String propertyPath, String message) {
            this.propertyPath = propertyPath;
            this.message = message;
        }

        public String getPropertyPath() {
            return propertyPath;
        }

        public void setPropertyPath(String propertyPath) {
            this.propertyPath = propertyPath;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

}
